---
title: Компоненты
description: Введение в синтаксис .astro компонента.
i18nReady: true
---

**Компоненты Astro** являются основными строительными блоками любого проекта Astro. Они представляют собой HTML шаблоны, которые не требуют выполнения на стороне клиента. Определить компонент Astro можно по расширению файла: `.astro`.

Компоненты Astro чрезвычайно гибки. Часто компонент Astro будет содержать некоторый **повторно используемый UI на странице**, например заголовок или карточку профиля. В других случаях компонент Astro может содержать небольшой фрагмент HTML, например набор общих `<meta>` тегов, которые упрощают работу с SEO. Компоненты Astro могут даже содержать макет страницы целиком.

Самое главное, что нужно знать о компонентах Astro, - это то, что **они не отрисовываются на клиенте**. Они преобразуются в HTML либо во время сборки, либо с использованием [рендеринга на стороне сервера (SSR)](/ru/guides/server-side-rendering/). Вы можете включить JavaScript-код внутри вашего компонента frontmatter, и он весь будет удален с конечной страницы, отправленной в браузеры ваших пользователей. В результате получается более быстрый сайт с нулевым использованием JavaScript по умолчанию.

Когда вашему компоненту Astro действительно требуется интерактивность на стороне клиента, вы можете добавить [стандартные теги HTML `<script>`](/ru/guides/client-side-scripts/) или [компоненты UI фреймворков](/ru/guides/framework-components/#hydrating-interactive-components).


## Структура компонента

Компонент Astro состоит из двух основных частей: **Скрипта компонента** и **Шаблона компонента**. Каждая часть выполняет свою работу, но вместе они обеспечивают структуру, которая одновременно проста в использовании и достаточно выразительна, чтобы справиться с тем, что вы захотите создать.

```astro title="src/components/EmptyComponent.astro"
---
// Скрипт компонента (JavaScript)
---
<!-- Шаблон компонента (HTML + выражения JS) -->
```

### Скрипт компонента

Astro использует ограждение кода (`---`) для идентификации скрипта в вашем компоненте Astro. Если вы когда-либо писали Markdown раньше, возможно, вы уже знакомы с похожей концепцией, называемой *frontmatter*. Идея Astro о скрипте компонента была непосредственно вдохновлена этой концепцией.

Вы можете использовать скрипт компонента для написания любого кода JavaScript, необходимого для визуализации шаблона. Это может включать в себя:

- импорт других Astro компонентов
- импорт компонентов из других фреймворков, таких как React
- импорт данных, например файла JSON
- получение контента из API или базы данных
- создание переменных, на которые вы будете ссылаться в своем шаблоне


```astro title="src/components/MyComponent.astro"
---
import SomeAstroComponent from '../components/SomeAstroComponent.astro';
import SomeReactComponent from '../components/SomeReactComponent.jsx';
import someData from '../data/pokemon.json';

// Доступ к входным параметрам компонента, таким как `<X title="Hello, World" />`
const {title} = Astro.props;
// Получение внешних данных, даже из приватного API или базы данных
const data = await fetch('SOME_SECRET_API_URL/users').then(r => r.json());
---
<!-- Здесь ваш шаблон! -->
```

Ограждение кода предназначено для того, чтобы гарантировать, что JavaScript, который вы пишете в нем, не ускользнет в ваше внешнее приложение и не попадет в руки вашего пользователя. Вы можете безопасно писать здесь ресурсоёмкий или конфиденциальный код (например, вызов вашей личной базы данных), не беспокоясь о том, что он когда-либо попадет в браузер вашего пользователя.

:::tip
Вы даже можете использовать TypeScript в скрипте вашего компонента!
:::

### Шаблон компонента

Шаблон компонента находится под ограждением кода и определяет вывод HTML вашего компонента.

Если вы напишете здесь простой HTML, ваш компонент будет отображать этот HTML на любой странице Astro, в которую он импортирован и используется.

Однако, [синтаксис Astro](/ru/basics/astro-syntax/) так же поддерживает **JavaScript выражения**, Astro [`<style>`](/ru/guides/styling/#styling-in-astro) и [`<script>`](/ru/guides/client-side-scripts/#использование-script-в-astro) теги, **импортированные компоненты**, и [**специальные Astro директивы**](/ru/reference/directives-reference/). Данные и значения, определенные в скрипте компонента, можно использовать в шаблоне компонента для создания динамически создаваемого HTML.

```astro title="src/components/MyFavoritePokemon.astro"
---
// Здесь ваш скрипт компонента!
import Banner from '../components/Banner.astro';
import ReactPokemonComponent from '../components/ReactPokemonComponent.jsx';
const myFavoritePokemon = [/* ... */];
const { title } = Astro.props;
---
<!-- Поддерживаются HTML коментарии! -->
{/* JS comment syntax is also valid! */}

<Banner />
<h1>Hello, world!</h1>

<!-- Используйте входные параметры и другие переменные из скрипта компонента.: -->
<p>{title}</p>

<!-- Включите другие компоненты инфраструктуры пользовательского интерфейса с помощью директивы `client`: для гидратации: -->
<ReactPokemonComponent client:visible />

<!-- Смешивайте HTML с выражениями JavaScript, аналогично JSX.: -->
<ul>
  {myFavoritePokemon.map((data) => <li>{data.name}</li>)}
</ul>

<!-- Используйте директиву шаблона для создания имен классов из нескольких строк или даже объектов! -->
<p class:list={["add", "dynamic", {classNames: true}]} />
```

## Компонентный дизайн

Компоненты спроектированы так, чтобы их можно было **повторно использовать** и **компоновать**. Вы можете использовать компоненты внутри других компонентов для создания более продвинутого пользовательского интерфейса. Например, компонент `Button` можно использовать для создания компонента `ButtonGroup`:

```astro title="src/components/ButtonGroup.astro"
---
import Button from './Button.astro';
---
<div>
  <Button title="Button 1" />
  <Button title="Button 2" />
  <Button title="Button 3" />
</div>
```


## Входные параметры компонента

Компонент Astro может определять и принимать параметры. Эти входные параметры затем становятся доступными для шаблона компонента для рендеринга HTML. Входные параметры доступны в глобальном объекте `Astro.props` в вашем скрипте.

Вот пример компонента, который получает входные параметры `greeting` и `name`. Обратите внимание, что получаемые входные параметры деструктурированы из глобального объекта `Astro.props`.

```astro "Astro.props"
---
// src/components/GreetingHeadline.astro
// Применение: <GreetingHeadline greeting="Howdy" name="Partner" />
const { greeting, name } = Astro.props;
---
<h2>{greeting}, {name}!</h2>
```

Этот компонент при импорте и визуализации в других компонентах Astro, макетах или страницах может передавать эти параметры в качестве атрибутов:

```astro /(\w+)=\S+/
---
// src/components/GreetingCard.astro
import GreetingHeadline from './GreetingHeadline.astro';
const name = "Astro"
---
<h1>Greeting Card</h1>
<GreetingHeadline greeting="Hi" name={name} />
<p>I hope you have a wonderful day!</p>
```

Вы также можете определить свои входные параметры с помощью TypeScript с интерфейсом типа `Props`. Astro автоматически подхватит интерфейс `Props` в вашем frontmatter и выдаст предупреждения/ошибки типа. Этим входным параметрам также могут быть присвоены значения по умолчанию при деструктуризации из `Astro.props`.

```astro ins={3-6}
---
// src/components/GreetingHeadline.astro
interface Props {
  name: string;
  greeting?: string;
}

const { greeting = "Hello", name } = Astro.props;
---
<h2>{greeting}, {name}!</h2>
```

Свойствам компонента могут быть присвоены значения по умолчанию, которые можно использовать, если они не указаны.

```astro ins="= \"Hello\"" ins="= \"Astronaut\""
---
// src/components/GreetingHeadline.astro
const { greeting = "Hello", name = "Astronaut" } = Astro.props;
---
<h2>{greeting}, {name}!</h2>
```

## Слоты

`<slot />` это заполнитель для внешнего HTML-содержимого, позволяющий вставлять дочерние элементы из других файлов в шаблон компонента.

По умолчанию все дочерние элементы, переданные компоненту, будут отображаться в его `<slot />`

:::note
В отличие от _входных параметров_, которые являются атрибутами, передаваемыми компоненту Astro, доступными для использования во всем вашем компоненте с помощью `Astro.props`, _слоты_ отображают дочерние элементы HTML там, где они написаны.
:::

```astro "<slot />"
---
// src/components/Wrapper.astro
import Header from './Header.astro';
import Logo from './Logo.astro';
import Footer from './Footer.astro';

const { title } = Astro.props
---
<div id="content-wrapper">
  <Header />
  <Logo />
  <h1>{title}</h1>
  <slot />  <!-- дочерний элемент будет здесь -->
  <Footer />
</div>
```

```astro {6-7}
---
// src/pages/fred.astro
import Wrapper from '../components/Wrapper.astro';
---
<Wrapper title="Fred's Page">
  <h2>All about Fred</h2>
  <p>Here is some stuff about Fred.</p>
</Wrapper>
```

Этот шаблон является основой [Astro Макетов](/ru/basics/layouts/): целая страница HTML-контента может быть «обернута» тегами `<SomeLayoutComponent></SomeLayoutComponent>` и передана компоненту для отрисовки внутри определенных в нем общих элементов страницы.



### Именованые слоты

Компонент Astro также может иметь именованные слоты. Это позволяет передавать в местоположение слота только элементы HTML с соответствующим именем слота.

Слоты именуются с помощью атрибута `name`:

```astro /<slot .*?/>/
---
// src/components/Wrapper.astro
import Header from './Header.astro';
import Logo from './Logo.astro';
import Footer from './Footer.astro';

const { title } = Astro.props
---
<div id="content-wrapper">
  <Header />
  <slot name="after-header"/>  <!--  дочерние элементы с атрибутом `slot="after-header"` будут находиться здесь -->
  <Logo />
  <h1>{title}</h1>
  <slot />  <!--  дочерние элементы без `slot`, или с `slot="default"` будут находиться здесь -->
  <Footer />
  <slot name="after-footer"/>  <!--  дочерние элементы с атрибутом `slot="after-footer"` будут находиться здесь -->
</div>
```

Чтобы внедрить HTML-контент в определенный слот, используйте атрибут `slot` в любом дочернем элементе, чтобы указать имя слота. Все остальные дочерние элементы компонента будут вставлены в стандартный (безымянный) `<slot />`.


```astro /slot=".*?"/
---
// src/pages/fred.astro
import Wrapper from '../components/Wrapper.astro';
---
<Wrapper title="Fred's Page">
  <img src="https://my.photo/fred.jpg" slot="after-header">
  <h2>All about Fred</h2>
  <p>Here is some stuff about Fred.</p>
  <p slot="after-footer">Copyright 2022</p>
</Wrapper>
```

:::tip
Используйте атрибут `slot="my-slot"` в дочернем элементе, который вы хотите передать в соответствующий заполнитель `<slot name="my-slot" />` в вашем компоненте.
:::

Чтобы передать несколько HTML-элементов в заполнитель `<slot/>` компонента без обёртывающего `<div>`, используйте атрибут `slot=""` на компоненте [`<Fragment/>` Astro](/ru/reference/api-reference/#fragment-):

```astro title="src/components/CustomTable.astro" "<slot name="header"/>" "<slot name="body"/>"
---
//  Создание пользовательской таблицы с именованными заполнителями для заголовка и тела контента
---
<table class="bg-white">
  <thead class="sticky top-0 bg-white"><slot name="header" /></thead>
  <tbody class="[&_tr:nth-child(odd)]:bg-gray-100"><slot name="body" /></tbody>
</table>
```

Вставьте несколько строк и столбцов HTML-контента с помощью атрибута `slot=""`, чтобы указать содержимое `"header"` и `"body"`. Отдельные элементы HTML также можно стилизовать:

```astro title="src/components/StockTable.astro" {5-7, 9-13} '<Fragment slot="header">' '<Fragment slot="body">'
---
import CustomTable from './CustomTable.astro';
---
<CustomTable>
  <Fragment slot="header"> <!-- pass table header -->
    <tr><th>Product name</th><th>Stock units</th></tr>
  </Fragment>

  <Fragment slot="body"> <!-- pass table body -->
    <tr><td>Flip-flops</td><td>64</td></tr>
    <tr><td>Boots</td><td>32</td></tr>
    <tr><td>Sneakers</td><td class="text-red-500">0</td></tr>
  </Fragment>
</CustomTable>
```

Обратите внимание, что именованные слоты должны быть непосредственными дочерними элементами компонента. Вы не можете передавать именованные слоты через вложенные элементы.

:::tip
Именованные слоты также можно передавать в [компоненты UI фреймворков](/ru/guides/framework-components/)!
:::


:::note
Имя астро-слота не может быть сгенерировано динамически, например, в функции map. Если такая возможность необходима в компонентах UI фреймворка, то, возможно, лучше генерировать эти динамические слоты в самом фреймворке.
:::


### Резервный контент для слотов
Слоты также могут отображать **резервный контент**. Когда в слот не передаются соответствующие дочерние элементы, элемент `<slot />` отобразит свои собственные дочерние элементы-заполнители.

```astro {14}
---
// src/components/Wrapper.astro
import Header from './Header.astro';
import Logo from './Logo.astro';
import Footer from './Footer.astro';

const { title } = Astro.props
---
<div id="content-wrapper">
  <Header />
  <Logo />
  <h1>{title}</h1>
  <slot>
    <p>Это резервное содержимое, если в слот не передан дочерний элемент</p>
  </slot>
  <Footer />
</div>
```

### Перенос слотов

Слоты можно передавать другим компонентам. Например, при создании вложенных макетов:

```astro title="src/layouts/BaseLayout.astro" {9,12}
---
---
<html lang="en">
	<head>
		<meta charset="utf-8" />
		<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
		<meta name="viewport" content="width=device-width" />
		<meta name="generator" content={Astro.generator} />
    <slot name="head"/>
	</head>
	<body>
		<slot />
	</body>
</html>
```

```astro {6,7}
// src/layouts/HomeLayout.astro
---
import BaseLayout from "./BaseLayout.astro";
---
<BaseLayout>
  <slot name="head" slot="head"/>
  <slot />
</BaseLayout>
```

:::note
Именованные слоты могут быть переданы другому компоненту, используя атрибуты `name` и `slot` в теге `<slot />`
:::

Теперь содержимое стандартного(безымянного) слота и слота `head`, переданных в `HomeLayout`, будет перенесено в родительский компонент `BaseLayout`.


```astro
// src/pages/index.astro
---
import HomeLayout from "../layouts/HomeLayout.astro";
---

<HomeLayout>
	<title slot="head">Astro</title>
	<h1>Astro</h1>
</HomeLayout>
```


## HTML-компоненты

Astro поддерживает импорт и использование `.html` файлов в качестве компонентов или размещение этих файлов в подкаталоге `src/pages/` в качестве страниц. Возможно, вам захочется использовать HTML-компоненты, если вы повторно используете код с существующего сайта, созданного без фреймворка, или если вы хотите убедиться, что ваш компонент не имеет динамических функций.

HTML-компоненты должны содержать только валидный HTML, поэтому они лишены ключевых возможностей компонентов Astro:
- Они не поддерживают frontmatter, импорт на стороне сервера или динамические выражения.
- Любые теги `<script>` остаются неупакованными, и обрабатываются, как если бы у них был атрибут `is:inline`.
- Они могут только [ссылаться на ресурсы, которые находятся в папке `public/`](/ru/basics/project-structure/#public).

:::note
В HTML-компоненте элемент [`<slot />`](/ru/basics/astro-components/#слоты) будет работать так же, как и в компоненте Astro. Чтобы использовать элемент [HTML Web Component Slot](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot ), добавьте атрибут `is:inline` к вашему элементу `<slot>`.
:::

## Следующие шаги

import ReadMore from '~/components/ReadMore.astro';

<ReadMore>Узнайте больше об использовании [UI компонентов фреймворков](/ru/guides/framework-components/) в вашем проекте Astro.</ReadMore>